#pragma once

#include <iostream>
#include <string>
#include <memory>
#include <sstream>
#include <jsoncpp/json/json.h>

#include "Log.hpp"
#include "Common.hpp"

using namespace LogArea;
static const std::string sep = "\r\n";

// 打包, "len\r\nmessage\r\n" 格式
bool Encode(std::string &message)
{
    if (!message.size())
        return false;
    std::string package = std::to_string(message.size()) + sep + message + sep;
    message = package;
    return true;
}

// 解包
bool Decode(std::string &package_message, std::string *content)
{
    // 处理读到的消息是否完整且正确
    auto pos = package_message.find(sep);
    if (pos == std::string::npos)
        return false;

    // 获取消息长度
    std::string content_length_str = package_message.substr(0, pos);
    int conntent_length = std::stoi(content_length_str);

    int full_length = content_length_str.size() + conntent_length + 2 * sep.size();

    if (package_message.size() < full_length)
    {
        LOG(LogLevel::ERROR) << "读取到的消息不全";
        return false;
    }

    // 输出消息
    *content = package_message.substr(pos + sep.size(), conntent_length);

    package_message.erase(0, full_length); // 清掉读掉的消息
    return true;
}

// 请求,要求计算
class Request
{
public:
    Request() : _x(0), _y(0), _oper(0)
    {
    }

    Request(int x, int y, char oper) : _x(x), _y(y), _oper(oper)
    {
    }

    // 用于将对象序列化为JSON字符串
    bool Serialize(std::string &out_message)
    {
        // 定义一个Json::Value对象，用于构建JSON数据
        Json::Value root;
        root["x"] = _x;
        root["y"] = _y;
        root["oper"] = _oper;

        // 创建一个Json::StreamWriterBuilder对象，用于配置JSON的输出格式
        Json::StreamWriterBuilder wb;

        // 使用wb创建一个Json::StreamWriter的智能指针
        std::shared_ptr<Json::StreamWriter> w(wb.newStreamWriter());

        // 创建一个std::stringstream对象，用于存储JSON字符串
        std::stringstream ss;
        // 将root对象按照JSON的输出格式写入到ss字符串流中
        w->write(root, &ss);
        out_message = ss.str();
        return true;
    }

    // 反序列化
    bool Deserialize(std::string &in_message)
    {
        // root用于存放解析后的字符串
        Json::Value root;

        // read用于解析in_message
        Json::Reader read;

        // 将解析后的JSON字符串格入root中
        bool parsing = read.parse(in_message, root);
        if (!parsing)
        {
            LOG(LogLevel::ERROR) << "read.parse error";
            return false;
        }

        _x = root["x"].asInt();
        _y = root["y"].asInt();
        _oper = root["oper"].asInt();

        return true;
    }

    void Print()
    {
        std::cout << _x << std::endl;
        std::cout << _oper << std::endl;
        std::cout << _y << std::endl;
    }

    int X() const { return _x; }
    int Y() const { return _y; }
    char Oper() const { return _oper; }

    ~Request()
    {
    }

private:
    int _x;
    int _y;
    char _oper;
};

// 响应,计算结果
class Response
{
public:
    Response() : _result(0), _code(0)
    {
    }

    Response(int result, int code) : _result(result), _code(code)
    {
    }

    bool Serialize(std::string &out_message)
    {
        Json::Value root;
        root["result"] = _result;
        root["code"] = _code;

        Json::StreamWriterBuilder wb;
        std::shared_ptr<Json::StreamWriter> w(wb.newStreamWriter());

        std::stringstream ss;
        w->write(root, &ss);
        out_message = ss.str();

        return true;
    }

    bool Deserialize(std::string &in_message)
    {
        Json::Value root;
        Json::Reader read;

        bool parsing = read.parse(in_message, root);
        if (!parsing)
        {
            LOG(LogLevel::ERROR) << "read.parse error";
            return false;
        }

        LOG(LogLevel::DEBUG)<<"root[result].asInt(): "<<root["result"].asInt();
        _result = root["result"].asInt();
        _code = root["code"].asInt();


        LOG(LogLevel::DEBUG)<<"..............................................."<<_result;

        return true;
    }

    void Print()
    {
        std::cout << _result << std::endl;
        std::cout << _code << std::endl;
    }

    int Result() { return _result; }
    int Code() { return _code; }
    void SetResult(int result)
    {
        _result = result;
        LOG(LogLevel::DEBUG) << "_result: " << _result;
    }
    void SetCode(int code) { _code = code; }
    ~Response()
    {
    }

private:
    int _result; // 计算结果
    int _code;   // 错误码
};